package org.eden.karb.session.impl;

import org.apache.commons.lang.NotImplementedException;
import org.eden.karb.activity.exception.ActivityException;
import org.eden.karb.device.MonitorDevice;
import org.eden.karb.device.RecordDevice;
import org.eden.karb.device.audio.AudioDeviceService;
import org.eden.karb.exception.InvalidSessionIdException;
import org.eden.karb.exception.KarbException;
import org.eden.karb.exception.SessionDoesNotExistException;
import org.eden.karb.session.SessionManager;
import org.eden.karb.session.entity.ActiveSession;

import javax.annotation.Resource;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * {@inheritDoc}
 */
public class SessionManagerImpl implements SessionManager {

    @Resource
    private AudioDeviceService audioService;

    private Map<UUID, ActiveSession> sessions = new ConcurrentHashMap<UUID, ActiveSession>();

    private final Object sessionLock = new Object();

    /**
     * Creates a new audio activity and recorder devices. A new session will be registered with the created devices.
     *
     * @return the created session
     */
    public ActiveSession createSession() throws ActivityException {

        /* create the devices */
        MonitorDevice monitor = this.audioService.getDevice(MonitorDevice.class);
        RecordDevice recorder = this.audioService.getDevice(RecordDevice.class);

        /* create the session */
        ActiveSession session = new ActiveSession();
        session.setMonitor(monitor);
        session.setRecorder(recorder);
        session.setId(monitor.getKey());

        /* register the session */
        this.sessions.put(session.getId(), session);

        return session;
    }

    public void start(UUID sessionKey) {
        throw new NotImplementedException();
    }

    public ActiveSession getSession(UUID sessionKey) {
        return this.sessions.get(sessionKey);
    }

    public void updateSession(ActiveSession session) throws KarbException {
        if (this.sessions != null && session != null) {
            synchronized (sessionLock) {
                UUID sessionId = null;
                // session UUID is valid?
                if (session.getId() != null) {
                    sessionId = session.getId();
                    // session exists?
                    if (this.sessions.get(sessionId) != null) {
                        // update session
                        this.sessions.put(sessionId, session);
                    } else {
                        throw new SessionDoesNotExistException(sessionId);
                    }
                } else {
                    throw new InvalidSessionIdException(sessionId);
                }
            }
        }
    }
}
